home *** CD-ROM | disk | FTP | other *** search
/ MIDICraft's MIDINET CD-ROM / MIDICraft's MIDINET CD-ROM.iso / DOSUTILS / MIDICUT.ZIP / MIDICUT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-11  |  8.1 KB  |  362 lines

  1. // midicut written by Günter Nagler 1997 (gnagler@ihm.tu-graz.ac.at)
  2. #include "midiio.hpp"
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6.  
  7. static char* version = "midicut v1.0 by Günter Nagler (" __DATE__ ")";
  8.  
  9. char* input = 0;
  10. char* output = 0;
  11.  
  12. MidiWrite* write = 0;
  13.  
  14. int copychannel[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  15. unsigned long startms = 0;
  16. unsigned long endms = 0xFFFFFFFFUL;
  17. long startunit = -1; // will be calculated when reaching first track
  18. long endunit = -1;
  19. int quiet = 0;
  20.  
  21. class MidiCut : public MidiCopy
  22. {
  23. public:
  24.   MidiCut(char* name);
  25.  
  26.   virtual void track(int trackno, long length, int channel);
  27.   virtual void time(unsigned long ticks); // delay between events
  28.  
  29.   virtual void meta(int what, int len, unsigned char* data);
  30.   virtual void program(int prg, int channel);
  31.   virtual void control(int channel, int what, int val); // general controls
  32.   virtual void pitchbend(int channel, int val);
  33.   virtual void noteon(int channel, int note, int vel);
  34.   virtual void noteoff(int channel, int note, int vel);
  35.   virtual void polyaftertouch(int channel, int note, int val);
  36.   virtual void aftertouch(int channel, int val);
  37.   virtual void sysex(int syslen, unsigned char* sysdata);
  38.  
  39.   virtual void event(int what, int len = 0, unsigned char* data = 0);
  40.  
  41.   virtual void error(const char* msg);
  42.   virtual void warning(const char* msg);
  43.  
  44.   virtual void percent(int perc);
  45.  
  46.   int cutrange();
  47.   int cutstart();
  48.   int cutend();
  49.   int cutrange(unsigned long ms);
  50. };
  51.  
  52. MidiCut::MidiCut(char* name) : MidiCopy(name)
  53. {
  54. }
  55.  
  56. int MidiCut::cutrange(unsigned long ms)
  57. {
  58.   return (ms < startms || ms > endms);
  59. }
  60.  
  61. int MidiCut::cutstart()
  62. {
  63.   if (startunit >= 0)
  64.     return curunit_ < startunit;
  65.   return curms_ < startms;
  66. }
  67.  
  68. int MidiCut::cutend()
  69. {
  70.   if (endunit >= 0)
  71.      return curunit_ >= endunit;
  72.   return curms_ >= endms;
  73. }
  74.  
  75. int MidiCut::cutrange()
  76. {
  77.   return cutstart() || cutend();
  78. }
  79.  
  80. void MidiCut::track(int trackno, long length, int channel)
  81. {
  82.   MidiCopy::track(trackno, length, channel);
  83. }
  84.  
  85. void MidiCut::time(unsigned long units)
  86. {
  87. unsigned long nextms, nextrest;
  88.  
  89.   if (startunit >= 0)
  90.   {
  91.     if (curunit_ + units < startunit)
  92.       return;
  93.     if (curunit_ < startunit)
  94.       units -= startunit-curunit_;
  95.   }
  96.   else
  97.   {
  98.     calctime(units, nextms, nextrest);
  99.  
  100.     if (nextms < startms)
  101.       return;
  102.     startunit = calcunit(startms, 0);
  103.     units = curunit_ + units - startunit;
  104.   }
  105.   if (endunit >= 0)
  106.   {
  107.     if (curunit_ >= endunit)
  108.       return;
  109.     if (curunit_ + units >= endunit)
  110.       units = endunit - curunit_;
  111.   }
  112.   else
  113.   {
  114.     calctime(units, nextms, nextrest);
  115.     if (curms_ <= endms && nextms >= endms)
  116.     {
  117.       endunit = calcunit(endms, 0);
  118.       units = endunit - curunit_;
  119.     }
  120.     if (curms_ >= endms)
  121.       return;
  122.   }
  123.   MidiCopy::time(units);
  124. }
  125.  
  126. void MidiCut::meta(int what, int len, unsigned char* data)
  127. {
  128.   MidiCopy::meta(what, len, data);
  129. }
  130.  
  131. void MidiCut::program(int channel, int prg)
  132. {
  133.   if (cutend() ||!copychannel[channel])
  134.     return;
  135.   MidiCopy::program(channel, prg);
  136. }
  137.  
  138. void MidiCut::control(int channel, int what, int val)
  139. {
  140.   if (cutend() ||!copychannel[channel])
  141.     return;
  142.   MidiCopy::control(channel, what, val);
  143. }
  144.  
  145. void MidiCut::pitchbend(int channel, int val)
  146. {
  147.   if (cutend() ||!copychannel[channel])
  148.     return;
  149.   MidiCopy::pitchbend(channel, val);
  150. }
  151.  
  152. void MidiCut::noteon(int channel, int note, int vel)
  153. {
  154.   if (cutrange() || !copychannel[channel])
  155.     return;
  156.   MidiCopy::noteon(channel, note, vel);
  157. }
  158.  
  159. void MidiCut::noteoff(int channel, int note, int vel)
  160. {
  161.   if (cutstart() || !copychannel[channel])
  162.     return;
  163.   MidiCopy::noteoff(channel, note, vel);
  164. }
  165.  
  166. void MidiCut::polyaftertouch(int channel, int note, int val)
  167. {
  168.   if (cutend() ||!copychannel[channel])
  169.     return;
  170.   MidiCopy::polyaftertouch(channel, note, val);
  171. }
  172.  
  173. void MidiCut::aftertouch(int channel, int val)
  174. {
  175.   if (cutend() || !copychannel[channel])
  176.     return;
  177.   MidiCopy::aftertouch(channel, val);
  178. }
  179.  
  180. void MidiCut::sysex(int syslen, unsigned char* sysdata)
  181. {
  182.   if (cutend())
  183.     return;
  184.   MidiCopy::sysex(syslen, sysdata);
  185. }
  186.  
  187. void MidiCut::event(int what, int len, unsigned char* data)
  188. {
  189.   if (cutend())
  190.     return;
  191.   MidiCopy::event(what, len, data);
  192. }
  193.  
  194. void MidiCut::percent(int perc)
  195. {
  196.   if (!quiet)
  197.     fprintf(stderr, "%-3d%%\r", perc);
  198. }
  199.  
  200. void MidiCut::error(const char* msg)
  201. {
  202.   printf("Error: %s\n", msg);
  203.   exit(1);
  204. }
  205.  
  206. void MidiCut::warning(const char* msg)
  207. {
  208.   printf("Warning: %s\n", msg);
  209. }
  210.  
  211. void usage()
  212. {
  213.   fprintf(stderr, "midicut copies a part of a midi song into a new file\n");
  214.   fprintf(stderr, "usage: MidiCut [-q][-ch #[-#]][-from #][-till #] file.mid cutfile.mid\n");
  215.   fprintf(stderr, "-version\tget program version\n");
  216.   fprintf(stderr, "-q\tbe quiet\n");
  217.   fprintf(stderr, "-channel c[-d]\tcopy only selected channels c..d (1-16) to output\n");
  218.   fprintf(stderr, "-from #\tstart cut at second # (default: 0)\n");
  219.   fprintf(stderr, "-end #\tend cut at second # (default: end of song)\n");
  220.   exit(1);
  221. }
  222.  
  223. int main(int argc, char**argv)
  224. {
  225. int changed = 0;
  226.  
  227.   argc--; argv++;
  228.   while (argc > 0 && **argv == '-')
  229.   {
  230.     if (strncmp(*argv, "-version", 2) == 0)
  231.     {
  232.       fprintf(stderr, "%s\n", version);
  233.       argc--; argv++;
  234.       if (argc == 0)
  235.     return 0;
  236.       continue;
  237.     }
  238.     if (argc > 0 && strcmp(*argv, "-q") == 0)
  239.     {
  240.       quiet = 1;
  241.       argc--; argv++;
  242.       continue;
  243.     }
  244.     if (strncmp(*argv, "-channel", 2) == 0)
  245.     {
  246.     int firstchannel, secondchannel;
  247.  
  248.       argc--; argv++;
  249.       if (argc > 0 && sscanf(*argv, "%u-%u", &firstchannel, &secondchannel) == 2)
  250.       {
  251.     if (firstchannel <= 0 || secondchannel > 16)
  252.     {
  253.       fprintf(stderr, "channel number %s out of range 1-16\n", *argv);
  254.       firstchannel = secondchannel = -1;
  255.     }
  256.     else if (firstchannel > secondchannel)
  257.     {
  258.       fprintf(stderr, "%s: first channel number must be less than second one\n", *argv);
  259.       firstchannel = secondchannel = -1;
  260.     }
  261.     argc--; argv++;
  262.       }
  263.       else if (argc > 0 && isdigit(**argv))
  264.       {
  265.     firstchannel = atoi(*argv);
  266.     if (firstchannel <= 0 || firstchannel > 16)
  267.     {
  268.       fprintf(stderr, "channel number %s out of range 1-16\n", *argv);
  269.       firstchannel = -1;
  270.     }
  271.     secondchannel = firstchannel;
  272.     argc--; argv++;
  273.       }
  274.       else
  275.       {
  276.     fprintf(stderr, "option -channel expects channel number 1-16\n");
  277.     usage();
  278.     break;
  279.       }
  280.       for (int c = firstchannel; c <= secondchannel; c++)
  281.       {
  282.     copychannel[c-1] = 1;
  283.     changed++;
  284.       }
  285.       continue;
  286.     }
  287.     if (strncmp(*argv, "-from", 2) == 0)
  288.     {
  289.       argc--; argv++;
  290.       if (argc > 0 && isdigit(**argv))
  291.       {
  292.     startms = atol(*argv) * 1000; // millisec!
  293.     argc--; argv++;
  294.       }
  295.       else
  296.     fprintf(stderr, "option -from needs a time parameter (seconds)\n");
  297.       continue;
  298.     }
  299.     if (strncmp(*argv, "-till", 2) == 0)
  300.     {
  301.       argc--; argv++;
  302.       if (argc > 0 && isdigit(**argv))
  303.       {
  304.     endms = atol(*argv) * 1000; // millisec!
  305.     argc--; argv++;
  306.       }
  307.       else
  308.     fprintf(stderr, "option -till needs a time parameter (seconds)\n");
  309.       continue;
  310.     }
  311.     fprintf(stderr, "invalid option %s\n", *argv);
  312.     argc--; argv++;
  313.     usage();
  314.   }
  315.   if (argc < 2)
  316.     usage();
  317.  
  318.   input = argv[0];
  319.   output = argv[1];
  320.   if (strcmp(input, output) == 0)
  321.   {
  322.     fprintf(stderr, "cannot convert midi to same file\n");
  323.     return 1;
  324.   }
  325.   MidiCut midi(input);
  326.   if (!midi.getf())
  327.   {
  328.     perror(input);
  329.     return 1;
  330.   }
  331.   write = new MidiWrite(output);
  332.   if (!write)
  333.   {
  334.     fprintf(stderr, "out of memory\n");
  335.     return 1;
  336.   }
  337.   if (!write->getf())
  338.   {
  339.     perror(output);
  340.     return 1;
  341.   }
  342.   argc--; argv++;
  343.  
  344.   if (!changed)
  345.   {
  346.     // default: all channels
  347.     for (int c = 0; c < 16; c++)
  348.       copychannel[c] = 1;
  349.   }
  350.  
  351.   midi.setoutput(write);
  352.  
  353.   midi.options_ = OPTION_NOCONTROLS+OPTION_NOSYSEVENTS;
  354.   if (!midi.run())
  355.     fprintf(stderr, "%s: midi read error at %04lX\n", input, midi.getpos());
  356.  
  357.   delete write;
  358.  
  359. //  fprintf(stderr, "cut units %ld-%ld\n", startunit, endunit);
  360.   return 0;
  361. }
  362.